package com.shadowlight.hero_story;

import com.google.protobuf.GeneratedMessageV3;
import com.google.protobuf.Message;
import com.shadowlight.hero_story.msg.GameMsgProtocol;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Locale;

/**
 * @Description 消息识别器
 * @Author cz
 * @Date 2022/3/2
 */
@Slf4j
public final class GameMsgRecognizer {

    private GameMsgRecognizer() {
    }

    /**
     * 消息编码和消息实例map
     */
    private static final HashMap<Integer, GeneratedMessageV3> MSG_CODE_AND_MSG_INSTANCE_MAP = new HashMap<>();

    /**
     * 消息类和消息编码map
     */
    private static final HashMap<Class<?>, Integer> MSG_CLAZZ_AND_MSG_CODE_MAP = new HashMap<>();

    public static void init() {
        Class<?>[] clazz = GameMsgProtocol.class.getDeclaredClasses();

        for (Class<?> clz : clazz) {

            if (!GeneratedMessageV3.class.isAssignableFrom(clz)) {
                continue;
            }

            /*
              userlogincmd 变成这样再判断
              注意getName会附带包名称，所以用getSimpleName只会返回类名称
             */
            String clzName = clz.getSimpleName().toLowerCase(Locale.ROOT);

            for (GameMsgProtocol.MsgCode msgCode : GameMsgProtocol.MsgCode.values()) {
                String msgCodeClzName = msgCode.name().replaceAll("_", "").toLowerCase(Locale.ROOT);
                if (clzName.equalsIgnoreCase(msgCodeClzName)) {
                    try {
                        Object rtObj = clz.getDeclaredMethod("getDefaultInstance").invoke(clz);
                        MSG_CODE_AND_MSG_INSTANCE_MAP.put(msgCode.getNumber(), (GeneratedMessageV3) rtObj);

                        MSG_CLAZZ_AND_MSG_CODE_MAP.put(clz, msgCode.getNumber());
                        log.debug("{}<=====>{}", clz.getName(), msgCode.getNumber());
                    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                        log.error("消息类、消息码对应出现错误======>", e);
                    }
                }
            }
        }
    }

    public static Message.Builder getMessageBuilderByMsgCode(int msgCode) {
        GeneratedMessageV3 msgInstance = MSG_CODE_AND_MSG_INSTANCE_MAP.get(msgCode);
        if (msgInstance == null) return null;
        return msgInstance.newBuilderForType();
    }

    public static Integer getMsgCodeByMsgClazz(Class<?> clazz) {
        if (clazz == null) return null;
        return MSG_CLAZZ_AND_MSG_CODE_MAP.get(clazz);
    }
}
